package com.BEASTMODE.libs;



import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.BEASTMODE.games.SpeedPong.R;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;



public class OpenGL implements GLSurfaceView.Renderer
{
	private static OpenGL _highlander = null;
	
	GamePanel _panel;
	
	private float[] vMat = new float[16];
	private float[] pMat = new float[16];
	private float[] vpMat = new float[16];
	
	private Triangle testTri;
	private Triangle secondTri;
	CShader testShader;
	
	private int[] texID = new int[1];
	
	public static OpenGL GetInstance()
	{
		if (_highlander == null)
			return null;
		return _highlander;
	}
	
	public static OpenGL Initialize(GamePanel panel)
	{
		if (_highlander != null)
			return _highlander;
		_highlander = new OpenGL();
		_highlander._panel = panel;
		return _highlander;
	}
	
	public void onSurfaceCreated(GL10 gl, EGLConfig eglc)
	{ 
		GLES20.glClearColor(0.5f, 0.0f, 0.2f, 1.0f);
		GLES20.glEnable(GLES20.GL_TEXTURE_2D);
		GLES20.glEnable(GLES20.GL_BLEND);
		GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
		
		float triangleCoords[] = {
				// X Y Z
				-1.67f, 1.0f, 0.0f,
				-1.67f, -1.0f, 0.0f,
				1.67f, 1.0f, 0.0f
				
		};
		
		float secondaryCoords[] = {
				1.67f, -1.0f, 0.0f,
				1.67f, 1.0f, 0.0f,
				-1.67f, -1.0f, 0.0f
		};
		
		float texCoords[] = {
				0.0f, 1.0f,
				0.0f, 0.0f,
				1.0f, 1.0f
		};
		
		float texCoords1[] = {
				1.0f, 0.0f,
				1.0f, 1.0f,
				0.0f, 0.0f
		};
		
		testShader = new CShader();

		testShader.LoadShader(_panel._owner.getString(R.string.flatvert), _panel._owner.getString(R.string.flatfrag));
		
		testTri = new Triangle();
		secondTri = new Triangle();
		testTri.Init(triangleCoords, texCoords, testShader);
		secondTri.Init(secondaryCoords, texCoords1, testShader);
		
		
		GLES20.glGenTextures(1, texID, 0);
		
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texID[0]);
		
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
		
		GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
		GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
		
		
		//TEXTURE LOAD CODE TODO: MOVE THIS SHIT TO A FUNCTION
		Bitmap bmap = null;
		
		Resources resources = _panel._owner.getResources();
		
		Drawable image = resources.getDrawable(R.drawable.speedpongbreakdown);
		
		float density = resources.getDisplayMetrics().density;
		
		int originalWidth = (int)(image.getIntrinsicWidth() / density);
		int originalHeight = (int)(image.getIntrinsicHeight() / density);
		
		int powWidth = getNextHighestPO2(originalWidth);
		int powHeight = getNextHighestPO2(originalHeight);
		
		image.setBounds(0, 0, powWidth, powHeight);
		
		bmap = Bitmap.createBitmap(powWidth, powHeight, Bitmap.Config.ARGB_4444	);
		
		Canvas canvas = new Canvas(bmap);
		bmap.eraseColor(0);
		
		image.draw(canvas);
		
		GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmap, 0);
		bmap.recycle();
		
	}
	
	public void onSurfaceChanged(GL10 gl, int w, int h) 
	{
        GLES20.glViewport(0, 0, w, h);
        
		float ratio = (float) w / h;
		
		Matrix.frustumM(pMat, 0, -ratio, ratio, -1, 1, 3, 7);
		
		Matrix.setLookAtM(vMat, 0, 0, 0, -3, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
        
    }

	//
	// Render
	//
    public void onDrawFrame(GL10 gl) 
    {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        
       Matrix.multiplyMM(vpMat, 0, pMat, 0, vMat, 0);
       testTri.Draw(vpMat, texID[0]);
       secondTri.Draw(vpMat, texID[0]);
        
    }
    
    private int getNextHighestPO2(int n)
    {
    	n -= 1;
    	n = n | (n >> 1);
    	n = n | (n >> 2);
    	n = n | (n >> 4);
    	n = n | (n >> 8);
    	n = n | (n >> 16);
    	n = n | (n >> 32);
    	return n + 1;
    }
}
